﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml;

namespace DashFire
{
  internal class ResUpdateChecker //检查是否需要更新
  {
    #region 单例
    public static ResUpdateChecker Instance { get { return sInstance; } }
    private static ResUpdateChecker sInstance = new ResUpdateChecker();
    private ResUpdateChecker() { }
    #endregion

    public Coroutine StartCheck()
    {
      return CoroutineProxy.Instance.StartCoroutine(CheckCoroutine());
    }

    public List<string> GetNeedUpdateFileList()
    {
      return mFileNeedUpdate;
    }

    public bool HashVerify(string file) //校验
    {
      int index = file.LastIndexOf('/');
      string name = file.Substring(index + 1);
      index = name.LastIndexOf('.');
      name = name.Substring(0, index);  //获得文件名

      string md5 = AssetBundleUtils.GenFileMD5(file);
      string serverMD5;
      if(mServerMD5.TryGetValue(name, out serverMD5))
      {
        if(string.Equals(md5, serverMD5))
        {
          return true;
        }
        return false;
      }
      return true;
    }
    public void SaveLocalHash(string file)
    {
      int index = file.LastIndexOf('/');
      string name = file.Substring(index + 1);
      index = name.LastIndexOf('.');
      name = name.Substring(0, index);  //获得文件名
      mLocalMD5[name] = mServerMD5[name];

      XmlDocument xmlDocument = new XmlDocument();
      XmlElement rootXmlElement = xmlDocument.CreateElement("AssetBundlesMD5Info");

      foreach (var info in mLocalMD5)
      {
        XmlElement e = xmlDocument.CreateElement("Hash");
        e.SetAttribute("Name", info.Key);
        e.SetAttribute("Md5", info.Value);
        rootXmlElement.AppendChild(e);
      }
      string path = Application.persistentDataPath + mLocalRelativePath;

      xmlDocument.AppendChild(rootXmlElement);
      xmlDocument.Save(path);
    }

    private IEnumerator CheckCoroutine()
    {
      yield return LoadLocalMD5();
      yield return LoadServerMD5();
      CompareMD5();
    }

    private Coroutine LoadLocalMD5()
    {
      return UseWWW.Instace.Get(LocalPath, LoadLocal);
    }
    void LoadLocal(WWW www)
    {
      ResUpdateMessage.Instance.Log("Load Local Hash File");
      if (www.error == null)
      {
        LoadXml(www, mLocalMD5);
      }
      else
      {
        ResUpdateMessage.Instance.Log("Load Local Hash Failed : {0}", www.error);
      }
        
    }

    private Coroutine LoadServerMD5()
    {
      return UseWWW.Instace.Get(URL, LoadServer);
    }

    private void CompareMD5()
    {
      mFileNeedUpdate.Clear();
      string localmd5 = string.Empty;
      foreach (var item in mServerMD5)
      {
        if(mLocalMD5.TryGetValue(item.Key, out localmd5) == true)
        {
          if (localmd5 == item.Value)
            continue;
        }

        mFileNeedUpdate.Add(item.Key); 
      }
    }

    void LoadServer(WWW www)
    {
      if(www.error == null)
      {
        LoadXml(www, mServerMD5);
      }
      else
      {
        ResUpdateMessage.Instance.SetError(
          ResUpdateError.RequestServer_MD5_Error, www.error);
      }
    }

    void LoadXml(WWW www, Dictionary<string, string> d)
    {
      XmlDocument xml = new XmlDocument();
      xml.LoadXml(www.text);
      XmlNode xmlNode = xml.SelectSingleNode("AssetBundlesMD5Info");
      LoadFormXmlNode(xmlNode, d);
    }

    void LoadFormXmlNode(XmlNode node, Dictionary<string, string> d)
    {
      if (node == null)
        return;
      d.Clear();
      foreach (XmlElement e in node.ChildNodes)
      {
        string md5 = e.GetAttribute("Md5");
        string name = e.GetAttribute("Name");

        if (d.ContainsKey(name) == false)
        {
          d.Add(name, md5);

        }      
      }
    }

    public string LocalPath
    {
      get {
        if(mLocalPath == string.Empty)
        {
          mLocalPath = PathUtil.WWWPersistentDataPath(mLocalRelativePath);
        }
        return mLocalPath;
      }
      set { mLocalRelativePath = value; mLocalPath = string.Empty; }
    }
    private string mLocalPath = string.Empty;
    private string mLocalRelativePath = "/AssetBundlesHash.xml";

    public string URL { get; set; }

    private Dictionary<string, string> mLocalMD5 = new Dictionary<string, string>();
    private Dictionary<string, string> mServerMD5 = new Dictionary<string, string>();
    private List<string> mFileNeedUpdate = new List<string>();
  }
}
